using System;
using System.Collections.Generic;
using System.IO;
using System.Timers;

namespace awesome_log_system
{
	/**
	 * Класс, представляющий файл как приемник данных
	 */
	public class FileDataDestination : DataDestination, IDisposable
	{
		private FileInfo fileInfo = null;
		private StreamWriter outputStream = null;
		/*
		 * Буффер
		 */
		private List<string> data = new List<string>();
		private System.Timers.Timer timer;
		/*
		 * Режим работы приёмника-файла.
		 * true -- запись идёт в один файл. запись при каждом аппенде.
		 * false -- автоматический сброс буффера в файл каждый интервал времени
		 */
		private bool autoflush;
		string path;
		private bool _disposed;
		DateTime now;

		/**
		 * Конструктор по умолчанию
		 * 
		 * Открывает на дополнение поток log
		 */
		public FileDataDestination () : this("log")
		{
		}
		
		/**
		 * Конструктор для работы в режиме автоматического сброса. 
		 * 
		 * @param url Имя файла
		 * @param interval интервал в милисекундах
		 */
		public FileDataDestination (string url, double interval)
		{
			_disposed = false;
			autoflush = false;		
			
			timer = new System.Timers.Timer (interval);
			timer.AutoReset = true;
			timer.Elapsed += new ElapsedEventHandler(timedFlush);
			timer.Start();			
			
			path = url;
			now = System.DateTime.Now;
		}
		
		/**
		 * Конструктор, инициализирующий экземпляр названием файла
		 * 
		 * @param url Путь до файла
		 */
		public FileDataDestination (string url)
		{
			_disposed = false;
			fileInfo = new FileInfo (url);
			/*if (fileInfo.Exists == false) {
				fileInfo.Create ();
			}*/
			outputStream = fileInfo.AppendText();
			outputStream.AutoFlush = true;
			autoflush = true;
		}

		/**
		 * Запись в конец файла
		 * 
		 * @param content Сожержимое для записи
		 */
		public void append (string content)
		{
			if (autoflush == true )
			{
				outputStream.WriteLine (content);
			}
			else
			{
				data.Add (content);
			}
		}
		
		/*
		 * Сброс буффера по будильнику.
		 * Если с момента предыдущего сброса не в лог постепило ни одной записи, дамп не происходит.
		 */
		private void timedFlush (object source, ElapsedEventArgs e)
		{
			if (data.Count != 0)
			{
				string url = path + "." + now.ToString("F");
				File.WriteAllLines(url, data);
				data.Clear();
				now = System.DateTime.Now;
			}
		}
		
		/*
		 * Принудительный сброс буффера. Применять только в конце, иначе файл будет перезаписан!
		 */
		private void mandatoryFlush ()
		{
			string url = path + "." + now.ToString("F");
			File.WriteAllLines(url,  data);			
		}
		
		public void Dispose()
		{
			if (autoflush == true)
			{
				outputStream.Close (); /*Делает outputStream.Flush() и вызывает outputStream.Dispose()*/
			}
			else
			{
				mandatoryFlush();
				timer.Dispose();
			}
			_disposed = true;
		}
	}
}